package SpidersManager;

##########################
#     OmnibusProxy       #
#    Krzysztof Ulman     #
# Politechnika Krakowska #
#      Kraków 2012       #
##########################

use strict;
use warnings;
use encoding 'utf8';

use Try::Tiny;

use AppConfig;
use Database;
use NewContentManager;
use ResultsManager;
use SearcherDto;
use Spider;
use StatementsUtils;

#handler do bazy
our $db;

#key=nazwa wyszukiwarki, value=Spider.pm
#my %spiders;

#konstruktor
sub new {
	shift;
	my $self = {};
	bless $self;

	if(!$db) {
		$db = Database->new();
	}
	
	return $self;
}

#przygotowuje pajaki do pracy
sub prepare {
	my $self = shift;
	#pobranie z bazy listy aktywnych wyszukiwarek
	my @searchersList = @{$db->getSearchers()};
	
	my %spiders;
	my $result = 1;
	#dla kazdej wyszukiwarki tworzymy osobnego pajaka
	foreach my $searcherDto (@searchersList) {
		my $keyName = $searcherDto->getName();
		try {
			my $spider = Spider->new();
			$spider->prepare($searcherDto);
			$spiders{$keyName} = $spider;
		} catch {
			my $e = $_;
			Screen->printAndLogFatal('Nie mozna skonfigurowac wyszukiwarki ' . $keyName . ': ' . $e);
			$result = 0;
		};
	}
	$self->{spiders} = \%spiders;
	
	return $result;
}

#zbieraj informacje na temat podanej frazy
sub collect {
	my $self = shift;
	my $statementDto = shift;
	my $MAX_RESULTS_PER_STATEMENT = AppConfig->getProperty('MAX_RESULTS_PER_STATEMENT');
	
	my $preparedStatement = StatementsUtils->prepareStatementForSearcher(
								$statementDto->getStatement(), 
								AppConfig->getProperty('PREPARE_STATEMENT_MODE'));
	
	my $resultsManager = ResultsManager->new();
	$resultsManager->setStatementDto($statementDto);
	
	#dla kazdej wyszukiwarki
	my $errors = 0;
	my %spiders = %{$self->{spiders}};
	foreach my $keyName (keys(%spiders)) {
		my $spider = $spiders{$keyName};
		try {
			#adres bazowy wyszukiwarki do utworzenia adresow bezwzglednych
			my $urlBase = undef;
			if($spider->getSearcherDto()->isRewriteUrlToAbsolute()) {
				$urlBase = $spider->getSearcherDto()->getUrl();
			}

			#pobranie wyniku (strona pierwsza)
			Screen->printAndLogDebug('Pobieram strone wynikow nr 1 dla frazy ' . '{' . $preparedStatement . '} z ' 
										. $spider->getSearcherDto()->getName());
			my $content = $spider->doQuery($preparedStatement);
			#przygotowanie do przetworzenia wyniku
			my $contentManager = NewContentManager->new($spider->getSearcherDto()->getName(), $urlBase);
			my $searcherId = $spider->getSearcherDto()->getSearcherId();
			$contentManager->configureResultsBoxAttributes(
				AppConfig->getProperty('RESULTS_TAG_NAME', $searcherId),
				AppConfig->getProperty('RESULTS_TAG_ATTRIBUTE_NAME', $searcherId),
				AppConfig->getProperty('RESULTS_TAG_ATTRIBUTE_VALUE', $searcherId),
				AppConfig->getProperty('RESULTS_BOX_TYPE', $searcherId),
				AppConfig->getProperty('NOT_DIRECT_URL_PREFIX', $searcherId),
				AppConfig->getProperty('NOT_DIRECT_URL_PREFIX_BAD', $searcherId));
			
			my $isLastPage = 0;
			#przetworzenie wyniku
			try {
				$contentManager->doWork($content);
			} catch {
				my $e = $_;
				Screen->printAndLogWarn('Cos nie tak, czyzby nie bylo wynikow dla tej frazy? ' . $e);
				$isLastPage = 1;
				#zwolnienie pamieci w przypadku jak poleci exception
				$contentManager->doDelete();
			};

			#pobranie kolejnych stron
			my $pageNum = 1;
			while($contentManager->getResultsNumber() < $MAX_RESULTS_PER_STATEMENT 
					&& $contentManager->getNextPageUrl() ne ''
					&& $contentManager->getFoundResultsOnCurrentPage() > 0
					&& $isLastPage == 0) {
				Screen->printAndLogDebug('Pobieram strone wynikow nr ' . ++$pageNum . ' dla frazy {' . $preparedStatement 
											. '} z ' . $spider->getSearcherDto()->getName());
				$content = $spider->doGet($contentManager->getNextPageUrl());
				try {
					$contentManager->doWork($content);
				} catch {
					my $e = $_;
					Screen->printAndLogDebug('Cos nie tak, czyzby to byla ostatnia strona? ' . $e);
#					Screen->printAndLogDebug("=======================\n=======================\n=======================\n" 
#											. $content 
#											. "\n=======================\n=======================\n=======================\n");
					$isLastPage = 1; #przerwanie petli
					#zwolnienie pamieci w przypadku jak poleci exception
					$contentManager->doDelete();
				};
			}

			#zapis wynikow do bazy
			$resultsManager->setSearcherDto($spider->getSearcherDto());		
			$resultsManager->saveResults($contentManager->getResultList());
		} catch {
			my $e = $_;
			my $message = 'BLAD podczas pobierania frazy {' . $preparedStatement . '} z wyszukiwarki '
							 . $keyName . ': ' . $e;
			$resultsManager->storeErrorMessage($message);
			Screen->printAndLogError($message);
			$errors++;
		};
	}
	
	my $spidersNum = scalar(keys(%spiders));
	if($errors < $spidersNum) {
		#obliczenie pozycji dla kazdego URLa
		$resultsManager->computeGlobalRank($spidersNum - $errors);
	}
}

1;